package com.hyts.classcode.compiler.handler.impl;


import com.hyts.classcode.classload.config.ClassloaderConfig;
import com.hyts.classcode.classload.load.LocalClassLoader;
import com.hyts.classcode.compiler.bean.JavaSourceObject;
import com.hyts.classcode.compiler.handler.SourceCompiler;
import com.hyts.guava.String.Strings;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Locale;
import java.util.logging.Logger;

/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.compiler.handler
 * @author:Libo/Alex
 * @create-date:2019-05-26 23:05
 * @copyright:libo-hyts-github
 * @email:libo2dev@aliyun.com
 * @description:此类主要用于: java标准版本的源码编译功能
 */
public class StringSourceCompiler implements SourceCompiler<String> {


    Logger logger = Logger.getLogger(StringSourceCompiler.class.getName());


    @Override
    public Class compiler(String publicKindName,String sourceCode) {

        if(Strings.isBlank(sourceCode)) {
            throw new NullPointerException("传入的java源代码为空!");
        }
        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

        StandardJavaFileManager standardFileManager = javaCompiler.getStandardFileManager(null,
                Locale.CHINA, Charset.forName("UTF-8"));

        JavaSourceObject so = null;
        Path compilerPath = null;
        String publicKindNameBack = "";
        if(publicKindName.contains(".")) {
            publicKindNameBack = publicKindName;
            int index = publicKindNameBack.lastIndexOf(".");
            if (index > -1) {
                publicKindNameBack = publicKindNameBack.replace(".", File.separator).substring(0, index);
            }
            String publicKindNameBackName = publicKindName.replace(".", File.separator);
            so = new JavaSourceObject(publicKindNameBackName, sourceCode);
            compilerPath = Paths.get(ClassloaderConfig.DEFAULT_CLASS_COMPILER_PATH+File.separator+publicKindNameBack);
        }else{
            so = new JavaSourceObject(publicKindName, sourceCode);
            compilerPath = Paths.get(ClassloaderConfig.DEFAULT_CLASS_COMPILER_PATH);
        }
        try {
            if(!Files.exists(compilerPath)){
                Files.createDirectories(compilerPath);
            }
        } catch (IOException e) {
            logger.severe("生成编译目录失败");
        }
        //拼接参数
        Iterable options = Arrays.asList("-d", ClassloaderConfig.DEFAULT_CLASS_COMPILER_PATH);
        Iterable<? extends JavaFileObject> files = Arrays.asList(so);
        logger.info(String.format("java源码版本:%s",javaCompiler.getSourceVersions()));
        JavaCompiler.CompilationTask task =
                javaCompiler.getTask(null,standardFileManager,
                        null,options,null,files);
        task.setLocale(Locale.CHINA);
        Boolean result = task.call();
        if(result){
            if(publicKindNameBack.length() != 0){
                publicKindNameBack+=File.separator;
            }
            ClassLoader classLoader = new LocalClassLoader(ClassloaderConfig.DEFAULT_CLASS_COMPILER_PATH+ File.separator+publicKindNameBack);
            try {
                return classLoader.loadClass(publicKindName);
            } catch (ClassNotFoundException e) {
              return null;
            }
        }else{
            throw new IllegalStateException("编译Java代码失败!");
        }
    }

    public static void main(String[] args){
        ClassLoader classLoader = new LocalClassLoader("/Users/alex/Documents/我的代码/coffice-toolbox/coffice-toolbox-utils/coffice-toolbox-classcode/build/compile/"/*+publicKindNameBack*/);
        try {
            System.out.println(classLoader.loadClass("com.hyts.agent.compiler.CompilerSample"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
